package hr.fer.zesoi.neumre.logic;

import hr.fer.zesoi.neumre.TetrisBoardComponent;
import hr.fer.zesoi.neumre.tetriminos.Tetrimino;

public class TetrisBoard {

	private TetrisBoardComponent component;

	private int rows;

	private int cols;

	private int[][] board;

	public TetrisBoard(int rows, int cols) {

		this.rows = rows;
		this.cols = cols;

		this.board = new int[rows][cols];
		for (int row = 0; row < rows; row++)
			for (int col = 0; col < cols; col++)
				board[row][col] = 0;
	}

	public void setBoard(int[][] board) {

		this.board = board;
		this.rows = board.length;
		this.cols = board[0].length;

		this.alertComponent();
	}

	public void showTetrimino(Tetrimino tetrimino, int col, int row) {

		clearBoard();

		for (int piece = 0; piece < 4; piece++)
			board[row + tetrimino.getPixelRelLocs()[piece].getPosY()][col
					+ tetrimino.getPixelRelLocs()[piece].getPosX()] = 1;

		alertComponent();
	}

	public void dropTetrimino(Tetrimino tetrimino, int col) {

		for (int rowD = 0; rowD < rows; rowD++)
			for (int colD = 0; colD < cols; colD++)
				if (board[rowD][colD] == 2)
					board[rowD][colD] = 1;

		int currRow = rows + 2;

		outer: while (currRow >= 0) {

			for (int pixel = 0; pixel < 4; pixel++)
				if (currRow + tetrimino.getPixelRelLocs()[pixel].getPosY() < rows) {

					int lookingRow = currRow
							+ tetrimino.getPixelRelLocs()[pixel].getPosY();
					int lookingCol = col
							+ tetrimino.getPixelRelLocs()[pixel].getPosX();

					if (lookingRow < 0 || board[lookingRow][lookingCol] != 0) {

						currRow++;
						break outer;
					}
				}

			if (currRow == 0)
				break;

			currRow--;
		}

		for (int pixel = 0; pixel < 4; pixel++)
			if (currRow + tetrimino.getPixelRelLocs()[pixel].getPosY() < rows)
				board[currRow + tetrimino.getPixelRelLocs()[pixel].getPosY()][col
						+ tetrimino.getPixelRelLocs()[pixel].getPosX()] = 2;

		this.alertComponent();
	}

	public void dropRows() {

		for (int row = 0; row < rows; row++) {
			if (isRowFull(row)) {
				dropRow(row);
				row--;
			}
		}

		for (int row = 0; row < rows; row++)
			for (int col = 0; col < cols; col++)
				if (board[row][col] != 0)
					board[row][col] = 1;

		this.alertComponent();
	}

	private boolean isRowFull(int row) {

		for (int col = 0; col < cols; col++)
			if (board[row][col] == 0)
				return false;

		return true;
	}

	private void dropRow(int droppingRow) {
		for (int row = droppingRow + 1; row < rows; row++)
			for (int col = 0; col < cols; col++)
				board[row - 1][col] = board[row][col];

		for (int col = 0; col < cols; col++)
			board[rows - 1][col] = 0;
	}

	public void clearBoard() {

		this.board = new int[rows][cols];
		alertComponent();
	}

	public void registerComponent(TetrisBoardComponent component) {
		this.component = component;
	}

	public int getRows() {
		return rows;
	}

	public int getCols() {
		return cols;
	}

	public int getPixelValue(int row, int col) {
		return board[row][col];
	}

	private void alertComponent() {

		component.boardChanged();
	}
}
